<template>
  <a-modal
    :title='`授权「${user.username}」`'
    :width='640'
    :visible='visible'
    :confirmLoading='loading'
    :maskClosable='false'
    @ok='ok'
    @cancel='cancel'
  >
    <a-spin :spinning='assignedPermissionLoading' v-if='visible'>
      <a-card>
        <a-transfer
          :data-source='dataSource'
          :target-keys='targetKeys'
          :show-search='showSearch'
          :filter-option='(inputValue, item) => item.title.indexOf(inputValue) !== -1'
          :rowKey='record => record.key'
          :show-select-all='false'
          @change='onChange'
        >
          <template
            slot='children'
            slot-scope='{
          props: { direction, filteredItems, selectedKeys, disabled: listDisabled },
          on: { itemSelectAll, itemSelect },
        }'
          >
            <a-table
              :row-selection='
            getRowSelection({ disabled: listDisabled, selectedKeys, itemSelectAll, itemSelect })
          '
              :columns="direction === 'left' ? leftColumns : rightColumns"
              :data-source='filteredItems'
              size='small'
              :style="{ pointerEvents: listDisabled ? 'none' : null }"
              :custom-row='
            ({ key, disabled: itemDisabled }) => ({
              on: {
                click: () => {
                  if (itemDisabled || listDisabled) return;
                  itemSelect(key, !selectedKeys.includes(key));
                },
              },
            })
          '
            />
          </template>
        </a-transfer>
      </a-card>
    </a-spin>
  </a-modal>
</template>

<script>

import { Transfer } from 'ant-design-vue'
import difference from 'lodash/difference'

export default {
  components: { ATransfer: Transfer },
  props: {
    visible: {
      type: Boolean,
      required: true
    },
    loading: {
      type: Boolean,
      default: () => false
    },
    user: {
      type: Object,
      default: () => {
        return {
          name: ''
        }
      }
    }
  },
  data() {
    return {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 17 }
      },
      dataSource: [],
      targetKeys: [],
      showSearch: true,
      leftColumns: [
        {
          dataIndex: 'title',
          title: '未分配角色'
        }
      ],
      rightColumns: [
        {
          dataIndex: 'title',
          title: '已分配角色'
        }
      ],

      assignedPermissionLoading: false
    }
  },
  mounted() {
    this.getAssignedRoutes()
    this.$watch('user', val => {
      this.getAssignedRoles()
    })

  },
  methods: {
    getAssignedRoutes() {
      this.$api.role('', { disablePage: true }).then(res => {
        res.items.forEach(item => {
          this.dataSource.push({
            key: item.name,
            title: item.name
          })
        })
      })
    },
    getAssignedRoles() {
      this.assignedPermissionLoading = true
      this.$api.user(`/${this.user.id}/assigned-roles`).then(res => {
        this.targetKeys = []
        res.items.forEach(item => {
          this.targetKeys.push(item.name)
        })
        this.assignedPermissionLoading = false
      }).catch(() => {
        this.assignedPermissionLoading = false
      })
    },
    onChange(nextTargetKeys, direction, moveKeys) {

      if (direction === 'right') {  //添加
        this.$api.user(`/${this.user.id}/assign`, { roles: moveKeys }, 'POST')
      } else { //移除
        this.$api.user(`/${this.user.id}/revoke`, { roles: moveKeys }, 'POST')
      }

      this.targetKeys = nextTargetKeys
    },
    triggerShowSearch(showSearch) {
      this.showSearch = showSearch
    },
    getRowSelection({ disabled, selectedKeys, itemSelectAll, itemSelect }) {
      return {
        getCheckboxProps: item => ({ props: { disabled: disabled || item.disabled } }),
        onSelectAll(selected, selectedRows) {
          const treeSelectedKeys = selectedRows
            .filter(item => !item.disabled)
            .map(({ key }) => key)
          const diffKeys = selected
            ? difference(treeSelectedKeys, selectedKeys)
            : difference(selectedKeys, treeSelectedKeys)
          itemSelectAll(diffKeys, selected)
        },
        onSelect({ key }, selected) {
          itemSelect(key, selected)
        },
        selectedRowKeys: selectedKeys
      }
    },
    ok() {
      this.$emit('ok', this.model)
    },
    cancel() {
      this.$emit('ok', this.model)
    }
  }
}
</script>
